//
// Created by Gao Shihao on 2023/8/31.
//

#ifndef PLC2LLVM_REFTYPE_H
#define PLC2LLVM_REFTYPE_H
#include <plc2llvm/TypeSystem/UserDefType.h>

#include <utility>

namespace plcst {

    class RefType: public UserDefType {
    public:

        explicit RefType(std::string&& name): UserDefType(std::move(name)), ref_to() {}

        explicit RefType(RefType* another) : UserDefType(another) { }

        Type* getRefTo();

        void setRefTo(std::unique_ptr<Type> t);

        [[nodiscard]] TypeKind getTypeKind() const override;

        virtual ConvertionSignal canConvertTo(std::shared_ptr<Type> dest) override{
            if(this->getTypeKind() == dest->getTypeKind()){ //类型相同
                return ConvertionSignal::IMPLICIT_CONVERSION;
            }
            return ConvertionSignal::ERROR_CONVERSION; // TODO
        }

        virtual TypeMsg typeSynthesisForBinaryOperator(ExpressionOperator op, std::shared_ptr<Type> another) override{
            return {nullptr, 2}; // TODO
        }

        virtual TypeMsg typeSynthesisForUnaryOperator(ExpressionOperator op) override {
            return {nullptr, 2};// TODO
        }

        virtual std::shared_ptr<Type> clone() override {
            return std::make_shared<RefType>(this);
        }

    private:
        std::unique_ptr<Type> ref_to;
        // 默认值为NULL，定义引用类型时，不能设置初始值
        // 定义变量的时候，才可以设置初始值。
    };

    TypeKind RefType::getTypeKind() const {
        return TypeKind::REF;
    }

    Type *RefType::getRefTo() {
        return ref_to.get();
    }

    void RefType::setRefTo(std::unique_ptr<Type> t) {
        ref_to = std::move(t);
    }
}
#endif //PLC2LLVM_REFTYPE_H
